module Analyzer.D.lexical.strings;

import Analyzer.D.util.textScanner;
import Analyzer.D.lexical.numbers;
import Analyzer.D.lexical.token_enum;
import Analyzer.D.lexical.coreLex;

public TOK scanWysiwygString( TextScanner sc )
{
    assert( sc.peek(2) == `r"` );
    sc.read(2); //consume r"
    sc.readUntil('"', `terminate r" wysiwyg string`);
    assert( sc.peek() == '"' );
    sc.read();
    scanStringPostfix( sc );
    return TOK.Tstring;
}


public TOK scanAlternateWysiwygString( TextScanner sc )
{
    assert( sc.peek() == '`' );
    sc.read(); //consume `
    sc.readUntil('`', "terminate wysiwyg string");
    assert( sc.peek() == '`' );
    sc.read(); //consume `
    scanStringPostfix( sc );
    return TOK.Tstring;
}

public TOK scanOldschoolString( TextScanner sc )
{
    scanOldSchool( '"', sc );
    scanStringPostfix( sc );
    return TOK.Tstring;
}

public TOK scanChar( TextScanner sc )
{
    scanOldSchool( '\'', sc );
    return TOK.Tcharconstant;
}

public TOK scanHexString( TextScanner sc )
{
    assert( sc.peek(2) == `x"` );
    sc.read(2); //consume x"
    sc.readUntil('"', "terminate hex string");
    assert( sc.peek() == '"' );
    sc.read();
    scanStringPostfix( sc );
    return TOK.Tstring;
}

public TOK scanEscapeSequence( TextScanner sc )
{
    assert( sc.peek() == '\\' );
    sc.read(); //consume \
    
    switch( sc.peek() )
    {
        case '\\':
        case '\'':
        case '?':
        case '"':
            sc.read();
            return TOK.Tescaped;
        case '&':
            sc.read();
            break;
        default:
            break;
    }
    
    bool isSequencePart( char c )
    {
        return isDigit(c) || isLetter(c);
    }

    while( isSequencePart( sc.peek() ) )
    {
        sc.read();
    }
    return TOK.Tstring;
}

void scanOldSchool( char bound, TextScanner sc )
{
    assert( sc.peek() == bound );
    sc.read();
    
    while( sc.peek() != bound )
    {
        char c = sc.read();
        if( c == '\\' ) //skip escape sequence, as it may containg a 'bound'
        {
            sc.read();
        }                
		if( sc.reachedEnd() ) 
		{
			throw new LexerException("Found EOF before terminating the string", sc); 
 		}
    }
    
    assert( sc.peek() == bound );
    sc.read();
}

void scanStringPostfix( TextScanner sc )
{
    switch( sc.peek() )
    {
        case 'c':
        case 'w':
        case 'd':
            sc.read();
            break;
        default:
            break;
    }
}


